package com.fyakm.daodejing.test001core;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Species {
    private String javaFilePath; // 存储Java文件的路径
    private List<String> inputDataList; // 存储自然环境输入的数据列表，用于测试Java代码
    private List<String> expectedOutputList; // 存储对应输入的预期输出列表

    public Species(String javaFilePath, List<String> inputDataList, List<String> expectedOutputList) {
        this.javaFilePath = javaFilePath;
        this.inputDataList = inputDataList;
        this.expectedOutputList = expectedOutputList;
    }

    // 获取Java文件路径的方法
    public String getJavaFilePath() {
        return javaFilePath;
    }

    // 执行Java代码并获取实际输出结果的方法（这里只是简单示意编译和运行逻辑，实际应用可能更复杂）
    public List<String> executeJavaCode() throws IOException {
        List<String> actualOutputList = new ArrayList<>();

        // 编译Java文件
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int compilationResult = compiler.run(null, null, null, javaFilePath);
        if (compilationResult == 0) {
            // 获取类名（假设Java文件中主类名与文件名一致，不含后缀，实际可调整）
            String className = getClassNameFromFilePath(javaFilePath);
            try {
                // 利用反射加载并执行类中的方法（这里假设存在一个固定的执行入口方法，比如'main' 方法或者自定义的 'execute' 方法等，需根据实际调整）
                Class<?> clazz = Class.forName(className);
                // 这里简单遍历输入数据列表，调用执行方法并获取输出，实际可能更复杂的参数传递等情况
                for (String input : inputDataList) {
                    // 假设类中有一个静态方法来处理输入并返回输出，这里需要根据实际Java代码的结构调整调用逻辑
                    String output = (String) clazz.getMethod("processInput", String.class).invoke(null, input);
                    actualOutputList.add(output);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return actualOutputList;
    }

    // 根据实际输出和预期输出对比，计算该物种对于当前环境输入的适应度的方法（简单示例，匹配越多适应度越高）
    public double calculateFitness(List<String> actualOutputList) {
        double correctCount = 0;
        for (int i = 0; i < actualOutputList.size(); i++) {
            if (actualOutputList.get(i).equals(expectedOutputList.get(i))) {
                correctCount++;
            }
        }
        return correctCount / actualOutputList.size();
    }

    // 从文件路径中获取类名的辅助方法（去除后缀名等）
    private String getClassNameFromFilePath(String filePath) {
        File file = new File(filePath);
        String fileName = file.getName();
        return fileName.substring(0, fileName.lastIndexOf('.'));
    }

    // 物种的变异方法，这里的变异可以是对Java文件内容进行修改（比如替换部分代码、添加语句等）
    // 示例中简单随机修改文件中的一行代码（很粗糙的方式，实际需要更合理语法分析等支持）
    public void mutate(double mutationRate) {
        try {
            String fileContent = new String(Files.readAllBytes(Paths.get(javaFilePath)));
            String[] lines = fileContent.split("\n");
            Random random = new Random();
            for (int i = 0; i < lines.length; i++) {
                if (random.nextDouble() < mutationRate) {
                    // 简单地在该行代码末尾添加一个随机字符串来模拟变异（实际要遵循Java语法等）
                    lines[i] += " // Mutated part: " + random.nextInt(100);
                }
            }
            String newFileContent = String.join("\n", lines);
            Files.write(Paths.get(javaFilePath), newFileContent.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void setJavaFilePath(String javaFilePath) {
        this.javaFilePath = javaFilePath;
    }

    public List<String> getInputDataList() {
        return inputDataList;
    }

    public void setInputDataList(List<String> inputDataList) {
        this.inputDataList = inputDataList;
    }

    public List<String> getExpectedOutputList() {
        return expectedOutputList;
    }

    public void setExpectedOutputList(List<String> expectedOutputList) {
        this.expectedOutputList = expectedOutputList;
    }
}